//
//  ComputeProgram.m
//  DeferredLighting
//
//  Created by Holmes Futrell on 2/9/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "ComputeProgram.h"
#import "clb_program.h"
#import "clb_error.h"

@implementation ComputeProgram

@synthesize kernel;

-(id)initWithContext:(cl_context)c 
			deviceID:(cl_device_id)d
				file:(NSString *)path
		  kernelName:(NSString *)kernelName {
		
	return [ self initWithContext: c deviceID:d file:path kernelName:kernelName buildOptions: @""];
	
}
	

-(id)initWithContext:(cl_context)c 
			  deviceID:(cl_device_id)d
				file:(NSString *)path
		  kernelName:(NSString *)kernelName
		buildOptions:(NSString *)buildOptions {
	
	if ( self = [super init] ) {
		
		context = c;
		
		char *s = clb_stringWithPath([path UTF8String]);
		size_t len = strlen(s);
		if (!s) return nil;
	
		cl_int errcode;
		program = clCreateProgramWithSource(c, (cl_uint)1, (const char **)&s, &len, &errcode);
		
		clb_check_error_simple(errcode);
		
		if (program == 0) {
			return nil;
		}
		
		if ( buildOptions == nil ) {
			buildOptions = @"";
		}
		
		NSString *defaultOptions = @"-cl-fast-relaxed-math -cl-strict-aliasing";
		
		const char *fullOptions = [[NSString stringWithFormat:@"%@ %@", defaultOptions, buildOptions] UTF8String];
		
		// unsafe optimizations
		//char *buildOptions = "";
		
		errcode = clBuildProgram(program, 1, &d, fullOptions, NULL, NULL);

		print_build_info(program, d);
		
		clb_check_error_simple(errcode);
		
		if (!buid_succeeded(program, d)) {
			NSLog(@"build failed");
			return nil;
		}
		
		errcode = CL_SUCCESS;
		kernel = clCreateKernel(program, [kernelName UTF8String], &errcode);
		clb_check_error_simple(errcode);
		
		free(s);
		
		return self;
		
	}
	
	return nil;
	
}

-(void)dealloc {
	clReleaseKernel(kernel);
	kernel = 0;
	clReleaseProgram(program);
	program = 0;
	[super dealloc];
}

@end
